<!doctype html>




<html class="theme-next pisces" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  
  
    
  
  <link href="//cdn.staticfile.org/fancybox/2.1.5/jquery.fancybox.min.css" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  
    
      
    

    
  

  

  
    
      
    

    
  

  
    
      
    

    
  

  
    
    
    <link href="//fonts.lug.ustc.edu.cn/css?family=Monda:300,300italic,400,400italic,700,700italic|Roboto Slab:300,300italic,400,400italic,700,700italic|Lobster Two:300,300italic,400,400italic,700,700italic|PT Mono:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






  

<link href="//cdn.staticfile.org/font-awesome/4.6.2/css/font-awesome.min.css" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="Web,JavaScript," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />






<meta name="description" content="事件流JavaScript 与HTML 之间的交互是通过事件实现的。事件，就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件，以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型，支持页面的行为(JavaScript 代码)与页面的外观(HTML 和CSS 代码)之间的松散耦合。
IE9、Firefox、Opera、Safari 和Chrom">
<meta property="og:type" content="article">
<meta property="og:title" content="《 JavaScript 高级程序设计》备忘-第十三章-1">
<meta property="og:url" content="http://codingme.xyz/2016/10/12/javascript-note-13-1/index.html">
<meta property="og:site_name" content="CodingMe">
<meta property="og:description" content="事件流JavaScript 与HTML 之间的交互是通过事件实现的。事件，就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件，以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型，支持页面的行为(JavaScript 代码)与页面的外观(HTML 和CSS 代码)之间的松散耦合。
IE9、Firefox、Opera、Safari 和Chrom">
<meta property="og:updated_time" content="2016-10-18T06:23:42.163Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="《 JavaScript 高级程序设计》备忘-第十三章-1">
<meta name="twitter:description" content="事件流JavaScript 与HTML 之间的交互是通过事件实现的。事件，就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件，以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型，支持页面的行为(JavaScript 代码)与页面的外观(HTML 和CSS 代码)之间的松散耦合。
IE9、Firefox、Opera、Safari 和Chrom">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    sidebar: {"position":"right","display":"post"},
    fancybox: true,
    motion: false,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://codingme.xyz/2016/10/12/javascript-note-13-1/"/>





  <title> 《 JavaScript 高级程序设计》备忘-第十三章-1 | CodingMe </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  










  
  
    
  

  <div class="container one-collumn sidebar-position-right page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">CodingMe</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle"></p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup">
 <span class="search-icon fa fa-search"></span>
 <input type="text" id="local-search-input">
 <div id="local-search-result"></div>
 <span class="popup-btn-close">close</span>
</div>


    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
  <link itemprop="mainEntityOfPage" href="http://codingme.xyz/2016/10/12/javascript-note-13-1/">

  <span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="name" content="Huang SJ">
    <meta itemprop="description" content="">
    <meta itemprop="image" content="/uploads/avatar.jpg">
  </span>

  <span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="CodingMe">
    <span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
      <img style="display:none;" itemprop="url image" alt="CodingMe" src="">
    </span>
  </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                《 JavaScript 高级程序设计》备忘-第十三章-1
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            

            

            
          </span>

          

          
            
          

          

          
          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="事件流"><a href="#事件流" class="headerlink" title="事件流"></a>事件流</h1><p>JavaScript 与HTML 之间的交互是通过事件实现的。<br><strong>事件，就是文档或浏览器窗口中发生的一些特定的交互瞬间</strong>。<br>可以使用侦听器(或处理程序)来预订事件，以便事件发生时执行相应的代码。<br>这种在传统软件工程中被称为观察员模式的模型，支持页面的行为(JavaScript 代码)与页面的外观(HTML 和CSS 代码)之间的松散耦合。</p>
<p>IE9、Firefox、Opera、Safari 和Chrome 全都已经实现了“DOM2 级事件”模块的核心部分。<strong>IE8 是最后一个仍然使用其专有事件系统的主要浏览器。</strong><br>尽管所有主要浏览器已经实现了“DOM2 级事件”，但这个规范本身并没有涵盖所有事件类型。</p>
<h2 id="1事件流"><a href="#1事件流" class="headerlink" title="1事件流"></a>1事件流</h2><p>在单击按钮的同时，你也单击了按钮的容器元素，甚至也单击了整个页面。<br>事件流描述的是从页面中接收事件的顺序。<br>当时，IE 的事件流是事件冒泡流，而Netscape Communicator 的事件流是事件捕获流。</p>
<h3 id="事件冒泡"><a href="#事件冒泡" class="headerlink" title="事件冒泡"></a>事件冒泡</h3><p>即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收，然后逐级向上传播到较为不具体的节点(文档)。<br><a id="more"></a></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span>Event Bubbling Example<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"myDiv"</span>&gt;</span>Click Me<span class="tag">&lt;/<span class="name">div</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<p>如果你单击了页面中的<code>&lt;div&gt;</code>元素，那么这个click 事件的传播顺序：<br>(1) <code>&lt;div&gt;</code><br>(2) <code>&lt;body&gt;</code><br>(3) <code>&lt;html&gt;</code><br>(4) <code>document</code></p>
<p>click 事件首先在<code>&lt;div&gt;</code>元素上发生，而这个元素就是我们单击的元素。然后，click事件沿DOM树向上传播，在每一级节点上都会发生，直至传播到document 对象。</p>
<p>所有现代浏览器都支持事件冒泡，但在具体实现上还是有一些差别。IE5.5 及更早版本中的事件冒泡会跳过<code>&lt;html&gt;</code>元素(从<code>&lt;body&gt;</code>直接跳到document)。<br>IE9、Firefox、Chrome 和Safari 则将事件一直冒泡到window 对象。</p>
<h3 id="事件捕获"><a href="#事件捕获" class="headerlink" title="事件捕获"></a>事件捕获</h3><p>事件捕获的思想是不太具体的节点应该更早接收到事件，而最具体的节点应该最后接收到事件。<br>事件捕获的用意在于在事件到达预定目标之前捕获它。</p>
<p>以前面的HTML 页面作为演示事件捕获的例子,click事件的触发顺序是:<br>(1) <code>document</code><br>(2) <code>&lt;html&gt;</code><br>(3) <code>&lt;body&gt;</code><br>(4) <code>&lt;div&gt;</code></p>
<p>在事件捕获过程中，document 对象首先接收到click 事件，然后事件沿DOM 树依次向下，一直传播到事件的实际目标，即<code>&lt;div&gt;</code>元素。</p>
<p>IE9、Safari、Chrome、Opera和Firefox 目前也都支持这种事件流模型。<br>尽管“DOM2 级事件”规范要求事件应该从document 对象开始传播，但这些浏览器都是从window 对象开始捕获事件的。<br>由于老版本的浏览器不支持，因此很少有人使用事件捕获。<br>也建议放心地使用事件冒泡，在有特殊需要时再使用事件捕获。</p>
<h3 id="DOM事件流"><a href="#DOM事件流" class="headerlink" title="DOM事件流"></a>DOM事件流</h3><p>“DOM2级事件”规定的事件流包括三个阶段：<strong>事件捕获阶段、处于目标阶段和事件冒泡阶段。</strong></p>
<p>首先发生的是事件捕获，为截获事件提供了机会。<br>然后是实际的目标接收到事件。<br>最后一个阶段是冒泡阶段，可以在这个阶段对事件做出响应。</p>
<p>在DOM 事件流中，实际的目标(<code>&lt;div&gt;</code>元素)在捕获阶段不会接收到事件。<br>这意味着在捕获阶段，事件从document 到<code>&lt;html&gt;</code>再到<code>&lt;body&gt;</code>后就停止了。<br>下一个阶段是“处于目标”阶段，于是事件在<code>&lt;div&gt;</code>上发生，并在事件处理(后面将会讨论这个概念)中被看成冒泡阶段的一部分。<br>然后，冒泡阶段发生，事件又传播回文档。</p>
<p>多数支持DOM 事件流的浏览器都实现了一种特定的行为；即使“DOM2 级事件”规范明确要求捕获阶段不会涉及事件目标，<br>但IE9、Safari、Chrome、Firefox 和Opera 9.5 及更高版本都会在捕获阶段触发事件对象上的事件。<br>结果，就是有两个机会在目标对象上面操作事件。</p>
<p>IE9、Opera、Firefox、Chrome 和Safari 都支持DOM 事件流；<strong>IE8 及更早版本不支持DOM 事件流</strong>。</p>
<h2 id="事件处理程序"><a href="#事件处理程序" class="headerlink" title="事件处理程序"></a>事件处理程序</h2><p><strong>事件就是用户或浏览器自身执行的某种动作</strong>。诸如click、load 和mouseover，都是事件的名字。<br>而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。<br><strong>事件处理程序的名字以”on”开头</strong>，因此click 事件的事件处理程序就是onclick，load 事件的事件处理程序就是onload。</p>
<h3 id="HTML事件处理程序"><a href="#HTML事件处理程序" class="headerlink" title="HTML事件处理程序"></a>HTML事件处理程序</h3><p>某个元素支持的每种事件，都可以使用一个与相应事件处理程序同名的HTML 特性来指定。这个特性的值应该是能够执行的JavaScript 代码。<br><code>&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;alert(&#39;Clicked&#39;)&quot; /&gt;</code><br>这个操作是通过指定onclick 特性并将一些JavaScript代码作为它的值来定义的。<br>由于这个值是JavaScript，因此不能在其中使用未经转义的HTML 语法字符，例如和号(&amp;)、双引号(“”)、小于号(&lt;)或大于号(&gt;)。<br>为了避免使用HTML 实体，这里使用了单引号。<br>如果想要使用双引号:<br><code>&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;alert(&amp;quot;Clicked&amp;quot;)&quot; /&gt;</code></p>
<p>在HTML 中定义的事件处理程序可以包含要执行的具体动作，也可以调用在页面其他地方定义的脚本。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span><span class="javascript"></span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">showMessage</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Hello world!"</span>);</div><div class="line">&#125;</div><div class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"Click Me"</span> <span class="attr">onclick</span>=<span class="string">"showMessage()"</span> /&gt;</span></div></pre></td></tr></table></figure>
<p>事件处理程序中的代码在执行时，有权访问全局作用域中的任何代码。<br>这样指定事件处理程序具有一些独到之处。首先，这样会创建一个封装着元素属性值的函数。<br>这个函数中有一个局部变量event，也就是事件对象：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">&lt;!-- 输出 "click" --&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"Click Me"</span> <span class="attr">onclick</span>=<span class="string">"alert(event.type)"</span>&gt;</span></div></pre></td></tr></table></figure>
<p>通过event 变量，可以直接访问事件对象，你不用自己定义它，也不用从函数的参数列表中读取。<br>在这个函数内部，this 值等于事件的目标元素。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">&lt;!-- 输出 "Click Me" --&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"Click Me"</span> <span class="attr">onclick</span>=<span class="string">"alert(this.value)"</span>&gt;</span></div></pre></td></tr></table></figure>
<p>关于这个<strong>动态创建的函数</strong>，另一个有意思的地方是它扩展作用域的方式。<br>在这个函数内部，可以像访问局部变量一样访问document 及该元素本身的成员。<br>这个函数使用with 像下面这样扩展作用域:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    <span class="keyword">with</span>(<span class="built_in">document</span>)&#123;</div><div class="line">        <span class="keyword">with</span>(<span class="keyword">this</span>)&#123;</div><div class="line">            <span class="comment">//元素属性值</span></div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>如此一来，事件处理程序要访问自己的属性就简单多了。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">&lt;!-- 输出 "Click Me" --&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"Click Me"</span> <span class="attr">onclick</span>=<span class="string">"alert(value)"</span>&gt;</span></div></pre></td></tr></table></figure>
<p>如果当前元素是一个表单输入元素，则作用域中还会包含访问表单元素(父元素)的入口。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    <span class="keyword">with</span>(<span class="built_in">document</span>)&#123;</div><div class="line">        <span class="keyword">with</span>(<span class="keyword">this</span>.form)&#123;</div><div class="line">            <span class="keyword">with</span>(<span class="keyword">this</span>)&#123;</div><div class="line">            <span class="comment">//元素属性值</span></div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>这样扩展作用域的方式，无非就是想让事件处理程序无需引用表单元素就能访问其他表单字段。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">method</span>=<span class="string">"post"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"username"</span> <span class="attr">value</span>=<span class="string">""</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"Echo Username"</span> <span class="attr">onclick</span>=<span class="string">"alert(username.value)"</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></div></pre></td></tr></table></figure>
<p>在这个例子中，单击按钮会显示文本框中的文本。值得注意的是，这里直接引用了username 元素。</p>
<p>在HTML 中指定事件处理程序有两个缺点。首先，存在一个时差问题。<br>因为用户可能会在HTML 元素一出现在页面上就触发相应的事件，但当时的事件处理程序有可能尚不具备执行条件。<br>假设showMessage()函数是在按钮下方、页面的最底部定义的。<br>如果用户在页面解析showMessage()函数之前就单击了按钮，就会引发错误。<br>(思考：那么如何解决？先把按钮设置成disabled，等对应函数的脚本加载成功后改成可点击？)<br>很多HTML 事件处理程序都会被封装在一个try-catch 块中，以便错误不会浮出水面。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"Click Me"</span> <span class="attr">onclick</span>=<span class="string">"try&#123;showMessage();&#125;catch(ex)&#123;&#125;"</span>&gt;</span></div></pre></td></tr></table></figure>
<p>如果在showMessage()函数有定义之前单击了按钮，用户将不会看到JavaScript 错误，因为在浏览器有机会处理错误之前，错误就被捕获了。</p>
<p>另一个缺点是，这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。<br>不同JavaScript引擎遵循的标识符解析规则略有差异，很可能会在访问非限定对象成员时出错。<br>最后一个缺点是HTML 与JavaScript 代码紧密耦合。<br>如果要更换事件处理程序，就要改动两个地方：HTML 代码和JavaScript 代码。<br>所以许多开发人员摒弃HTML 事件处理程序，转而使用JavaScript 指定事件处理程序。</p>
<h3 id="DOM0-级事件处理程序"><a href="#DOM0-级事件处理程序" class="headerlink" title="DOM0 级事件处理程序"></a>DOM0 级事件处理程序</h3><p>通过JavaScript 指定事件处理程序的传统方式，就是将一个函数赋值给一个事件处理程序属性。<br>这种为事件处理程序赋值的方法是在第四代Web 浏览器中出现的，而且至今仍然为所有现代浏览器所支持。<br>原因一是简单，二是具有跨浏览器的优势。<br>要使用JavaScript 指定事件处理程序，首先必须取得一个要操作的对象的引用。</p>
<p>每个元素(包括window 和document)都有自己的事件处理程序属性，这些属性通常全部小写，例如onclick。<br>将这种属性的值设置为一个函数，就可以指定事件处理程序。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Clicked"</span>);</div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>在这些代码运行以前不会指定事件处理程序，因此如果这些代码在页面中位于按钮后面，就有可能在一段时间内怎么单击都没有反应。<br>使用DOM0 级方法指定的事件处理程序被认为是元素的方法。<br>因此，这时候的事件处理程序是在元素的作用域中运行；换句话说，程序中的this 引用当前元素。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="keyword">this</span>.id); <span class="comment">//"myBtn"</span></div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>实际上可以在事件处理程序中通过this 访问元素的任何属性和方法。<br>以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。<br>将事件处理程序设置为null 之后，再单击按钮将不会有任何动作发生。</p>
<p>如果使用HTML 指定事件处理程序，那么onclick 属性的值就是一个包含着在同名HTML 特性中指定的代码的函数。<br>而将相应的属性设置为null，也可以删除以这种方式指定的事件处理程序。</p>
<h3 id="DOM2-级事件处理程序"><a href="#DOM2-级事件处理程序" class="headerlink" title="DOM2 级事件处理程序"></a>DOM2 级事件处理程序</h3><p>“DOM2级事件”定义了两个方法，用于处理指定和删除事件处理程序的操作：addEventListener()和removeEventListener()。<br>所有DOM节点中都包含这两个方法，并且它们都接受3 个参数：要处理的事件名、作为事件处理程序的函数和一个布尔值。<br>最后这个布尔值参数如果是true，表示在捕获阶段调用事件处理程序；如果是false，表示在冒泡阶段调用事件处理程序。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.addEventListener(<span class="string">"click"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="keyword">this</span>.id);</div><div class="line">&#125;, <span class="literal">false</span>);</div></pre></td></tr></table></figure>
<p>与DOM0 级方法一样，这里添加的事件处理程序也是在其依附的元素的作用域中运行。<br>使用DOM2 级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.addEventListener(<span class="string">"click"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="keyword">this</span>.id);</div><div class="line">&#125;, <span class="literal">false</span>);</div><div class="line">btn.addEventListener(<span class="string">"click"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Hello world!"</span>);</div><div class="line">&#125;, f alse);</div></pre></td></tr></table></figure>
<p>这两个事件处理程序会按照添加它们的顺序触发，因此首先会显示元素的ID，其次会显示”Hello world!”消息。<br>通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除；<br>移除时传入的参数与添加处理程序时使用的参数相同。<br>这也意味着通过addEventListener()添加的匿名函数将无法移除。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//这里省略了其他代码</span></div><div class="line">btn.removeEventListener(<span class="string">"click"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; <span class="comment">//没有用！</span></div><div class="line">    alert(<span class="keyword">this</span>.id);</div><div class="line">&#125;, <span class="literal">false</span>);</div></pre></td></tr></table></figure>
<p>但实际上，第二个参数与传入addEventListener()中的那一个是完全不同的函数。<br>而传入removeEventListener()中的事件处理程序函数必须与传入addEventListener()中的相同。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line"><span class="keyword">var</span> handler = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="keyword">this</span>.id);</div><div class="line">&#125;;</div><div class="line">btn.addEventListener(<span class="string">"click"</span>, handler, <span class="literal">false</span>);</div><div class="line"><span class="comment">//这里省略了其他代码</span></div><div class="line">btn.removeEventListener(<span class="string">"click"</span>, handler, <span class="literal">false</span>); <span class="comment">//有效！</span></div></pre></td></tr></table></figure>
<p>大多数情况下，都是将事件处理程序添加到事件流的冒泡阶段，这样可以最大限度地兼容各种浏览器。<br>最好只在需要在事件到达目标之前截获它的时候将事件处理程序添加到捕获阶段。<br>如果不是特别需要，不建议在事件捕获阶段注册事件处理程序。</p>
<h3 id="IE事件处理程序"><a href="#IE事件处理程序" class="headerlink" title="IE事件处理程序"></a>IE事件处理程序</h3><p>attachEvent()和detachEvent()。<br>接受相同的两个参数：事件处理程序名称与事件处理程序函数。<br>由于IE8 及更早版本只支持事件冒泡，所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.attachEvent(<span class="string">"onclick"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Clicked"</span>);</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>attachEvent()的第一个参数是”onclick”，而非DOM 的addEventListener()方法中的”click”。<br>在IE 中使用attachEvent()与使用DOM0 级方法的主要区别在于事件处理程序的作用域。<br>在使用DOM0 级方法的情况下，事件处理程序会在其所属元素的作用域内运行；<br>在使用attachEvent()方法的情况下，事件处理程序会在全局作用域中运行，因此this 等于window。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.attachEvent(<span class="string">"onclick"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="keyword">this</span> === <span class="built_in">window</span>); <span class="comment">//true</span></div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>在编写跨浏览器的代码时，牢记这一区别非常重要。<br>attachEvent()方法也可以用来为一个元素添加多个事件处理程序。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line">btn.attachEvent(<span class="string">"onclick"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Clicked"</span>);</div><div class="line">&#125;);</div><div class="line">btn.attachEvent(<span class="string">"onclick"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Hello world!"</span>);</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>与DOM方法不同的是，这些事件处理程序不是以添加它们的顺序执行，而是以相反的顺序被触发。<br>首先看到的是”Hello world!”，然后才是”Clicked”。<br>使用attachEvent()添加的事件可以通过detachEvent()来移除，条件是必须提供相同的参数。<br>与DOM 方法一样，这也意味着添加的匿名函数将不能被移除。<br>不过，只要能够将对相同函数的引用传给detachEvent()，就可以移除相应的事件处理程序。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line"><span class="keyword">var</span> handler = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Clicked"</span>);</div><div class="line">&#125;;</div><div class="line">btn.attachEvent(<span class="string">"onclick"</span>, handler);</div><div class="line"><span class="comment">//这里省略了其他代码</span></div><div class="line">btn.detachEvent(<span class="string">"onclick"</span>, handler);</div></pre></td></tr></table></figure>
<p>这个例子将保存在变量handler 中的函数作为事件处理程序。因此，后面的detachEvent()可以使用相同的函数来移除事件处理程序。</p>
<h3 id="跨浏览器的事件处理程序"><a href="#跨浏览器的事件处理程序" class="headerlink" title="跨浏览器的事件处理程序"></a>跨浏览器的事件处理程序</h3><p>为了以跨浏览器的方式处理事件，不少开发人员会使用能够隔离浏览器差异的JavaScript 库，还有一些开发人员会自己开发最合适的事件处理的方法。<br>第一个要创建的方法是addHandler()，它的职责是视情况分别使用DOM0 级方法、DOM2 级方法或IE 方法来添加事件。<br>这个方法属于一个名叫EventUtil 的对象，将使用这个对象来处理浏览器间的差异。<br>addHandler()方法接受3 个参数：要操作的元素、事件名称和事件处理程序函数。</p>
<p>与addHandler()对应的方法是removeHandler()，它也接受相同的参数。<br>这个方法的职责是移除之前添加的事件处理程序——无论该事件处理程序是采取什么方式添加到元素中的，如果其他方法无效，默认采用DOM0 级方法。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> EventUtil = &#123;</div><div class="line">    addHandler: <span class="function"><span class="keyword">function</span>(<span class="params">element, type, handler</span>)</span>&#123;</div><div class="line">        <span class="keyword">if</span> (element.addEventListener)&#123;</div><div class="line">            element.addEventListener(type, handler, <span class="literal">false</span>);</div><div class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (element.attachEvent)&#123;</div><div class="line">            element.attachEvent(<span class="string">"on"</span> + type, handler);</div><div class="line">        &#125; <span class="keyword">else</span> &#123;</div><div class="line">            element[<span class="string">"on"</span> + type] = handler;</div><div class="line">        &#125;</div><div class="line">    &#125;,</div><div class="line">    removeHandler: <span class="function"><span class="keyword">function</span>(<span class="params">element, type, handler</span>)</span>&#123;</div><div class="line">        <span class="keyword">if</span> (element.removeEventListener)&#123;</div><div class="line">            element.removeEventListener(type, handler, <span class="literal">false</span>);</div><div class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (element.detachEvent)&#123;</div><div class="line">            element.detachEvent(<span class="string">"on"</span> + type, handler);</div><div class="line">        &#125; <span class="keyword">else</span> &#123;</div><div class="line">            element[<span class="string">"on"</span> + type] = <span class="literal">null</span>;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="keyword">var</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">"myBtn"</span>);</div><div class="line"><span class="keyword">var</span> handler = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">    alert(<span class="string">"Clicked"</span>);</div><div class="line">&#125;;</div><div class="line">EventUtil.addHandler(btn, <span class="string">"click"</span>, handler);</div><div class="line"><span class="comment">//这里省略了其他代码</span></div><div class="line">EventUtil.removeHandler(btn, <span class="string">"click"</span>, handler);</div></pre></td></tr></table></figure>
<p>首先都会检测传入的元素中是否存在DOM2 级方法。<br>如果存在DOM2 级方法，则使用该方法：传入事件类型、事件处理程序函数和第三个参数false(表示冒泡阶段)。<br>如果存在的是IE 的方法，则采取第二种方案。<br>最后一种可能就是使用DOM0 级方法(在现代浏览器中，应该不会执行这里的代码)。</p>
<p>addHandler()和removeHandler()没有考虑到所有的浏览器问题，例如在IE 中的作用域问题。<br>不过，使用它们添加和移除事件处理程序还是足够了。<br>此外还要注意，DOM0 级对每个事件只支持一个事件处理程序。(好在，只支持DOM0 级的浏览器已经没有那么多了)</p>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>


    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/Web/" rel="tag"># Web</a>
          
            <a href="/tags/JavaScript/" rel="tag"># JavaScript</a>
          
        </div>
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2016/10/09/javascript-note-12-4/" rel="next" title="《 JavaScript 高级程序设计》备忘-第十二章-4">
                <i class="fa fa-chevron-left"></i> 《 JavaScript 高级程序设计》备忘-第十二章-4
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2016/10/16/javascript-note-13-2/" rel="prev" title="《 JavaScript 高级程序设计》备忘-第十三章-2">
                《 JavaScript 高级程序设计》备忘-第十三章-2 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/uploads/avatar.jpg"
               alt="Huang SJ" />
          <p class="site-author-name" itemprop="name">Huang SJ</p>
          <p class="site-description motion-element" itemprop="description"></p>
        </div>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">75</span>
              <span class="site-state-item-name">日志</span>
            </a>
          </div>

          
            <div class="site-state-item site-state-categories">
              <a href="/categories">
                <span class="site-state-item-count">4</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-tags">
              <a href="/tags">
                <span class="site-state-item-count">9</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/hsj1992" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://twitter.com/hsj9527" target="_blank" title="Twitter">
                  
                    <i class="fa fa-fw fa-twitter"></i>
                  
                  Twitter
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://weibo.com/u/1694147905" target="_blank" title="Weibo">
                  
                    <i class="fa fa-fw fa-weibo"></i>
                  
                  Weibo
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.freecodecamp.cn/hsj1992" target="_blank" title="FreeCodeCamp">
                  
                    <i class="fa fa-fw fa-fire"></i>
                  
                  FreeCodeCamp
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://codepen.io/hsj1992/" target="_blank" title="codepen">
                  
                    <i class="fa fa-fw fa-codepen"></i>
                  
                  codepen
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://hsj1992.oschina.io/" target="_blank" title="码云镜像">
                  
                    <i class="fa fa-fw fa-code"></i>
                  
                  码云镜像
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://hsj1992.coding.me/" target="_blank" title="coding镜像">
                  
                    <i class="fa fa-fw fa-code"></i>
                  
                  coding镜像
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://hsj1992.github.io/" target="_blank" title="github镜像">
                  
                    <i class="fa fa-fw fa-code"></i>
                  
                  github镜像
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://codingme-6dd8a.firebaseapp.com" target="_blank" title="Firebase镜像">
                  
                    <i class="fa fa-fw fa-google"></i>
                  
                  Firebase镜像
                </a>
              </span>
            
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#事件流"><span class="nav-number">1.</span> <span class="nav-text">事件流</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1事件流"><span class="nav-number">1.1.</span> <span class="nav-text">1事件流</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#事件冒泡"><span class="nav-number">1.1.1.</span> <span class="nav-text">事件冒泡</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#事件捕获"><span class="nav-number">1.1.2.</span> <span class="nav-text">事件捕获</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#DOM事件流"><span class="nav-number">1.1.3.</span> <span class="nav-text">DOM事件流</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#事件处理程序"><span class="nav-number">1.2.</span> <span class="nav-text">事件处理程序</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#HTML事件处理程序"><span class="nav-number">1.2.1.</span> <span class="nav-text">HTML事件处理程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#DOM0-级事件处理程序"><span class="nav-number">1.2.2.</span> <span class="nav-text">DOM0 级事件处理程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#DOM2-级事件处理程序"><span class="nav-number">1.2.3.</span> <span class="nav-text">DOM2 级事件处理程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#IE事件处理程序"><span class="nav-number">1.2.4.</span> <span class="nav-text">IE事件处理程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#跨浏览器的事件处理程序"><span class="nav-number">1.2.5.</span> <span class="nav-text">跨浏览器的事件处理程序</span></a></li></ol></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2015 - 
  <span itemprop="copyrightYear">2016</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Huang SJ</span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>


        

        
      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  



  
  <script type="text/javascript" src="//cdn.staticfile.org/jquery/2.1.3/jquery.min.js"></script>

  
  <script type="text/javascript" src="//cdn.staticfile.org/fastclick/1.0.6/fastclick.min.js"></script>

  
  <script type="text/javascript" src="//cdn.staticfile.org/jquery_lazyload/1.9.7/jquery.lazyload.min.js"></script>

  
  <script type="text/javascript" src="//cdn.staticfile.org/velocity/1.2.1/velocity.min.js"></script>

  
  <script type="text/javascript" src="//cdn.staticfile.org/velocity/1.2.1/velocity.ui.min.js"></script>

  
  <script type="text/javascript" src="//cdn.staticfile.org/fancybox/2.1.5/jquery.fancybox.pack.js"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.0"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script>



  



  




	




  
  
  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length == 0) {
      search_path = "search.xml";
    }
    var path = "/" + search_path;
    // monitor main search box;

    function proceedsearch() {
      $("body").append('<div class="popoverlay">').css('overflow', 'hidden');
      $('.popup').toggle();
    }
    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';
      $.ajax({
        url: path,
        dataType: "xml",
        async: true,
        success: function( xmlResponse ) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = $( "entry", xmlResponse ).map(function() {
            return {
              title: $( "title", this ).text(),
              content: $("content",this).text(),
              url: $( "url" , this).text()
            };
          }).get();
          var $input = document.getElementById(search_id);
          var $resultContent = document.getElementById(content_id);
          $input.addEventListener('input', function(){
            var matchcounts = 0;
            var str='<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length > 1) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var content_index = [];
                var data_title = data.title.trim().toLowerCase();
                var data_content = data.content.trim().replace(/<[^>]+>/g,"").toLowerCase();
                var data_url = decodeURIComponent(data.url);
                var index_title = -1;
                var index_content = -1;
                var first_occur = -1;
                // only match artiles with not empty titles and contents
                if(data_title != '') {
                  keywords.forEach(function(keyword, i) {
                    index_title = data_title.indexOf(keyword);
                    index_content = data_content.indexOf(keyword);
                    if( index_title >= 0 || index_content >= 0 ){
                      isMatch = true;
                      if (i == 0) {
                        first_occur = index_content;
                      }
                    }

                  });
                }
                // show search results
                if (isMatch) {
                  matchcounts += 1;
                  str += "<li><a href='"+ data_url +"' class='search-result-title'>"+ data_title +"</a>";
                  var content = data.content.trim().replace(/<[^>]+>/g,"");
                  if (first_occur >= 0) {
                    // cut out 100 characters
                    var start = first_occur - 20;
                    var end = first_occur + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if(start == 0){
                      end = 50;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    var match_content = content.substring(start, end);
                    // highlight all keywords
                    keywords.forEach(function(keyword){
                      var regS = new RegExp(keyword, "gi");
                      match_content = match_content.replace(regS, "<b class=\"search-keyword\">"+keyword+"</b>");
                    });

                    str += "<p class=\"search-result\">" + match_content +"...</p>"
                  }
                  str += "</li>";
                }
              })};
            str += "</ul>";
            if (matchcounts == 0) { str = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>' }
            if (keywords == "") { str = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>' }
            $resultContent.innerHTML = str;
          });
          proceedsearch();
        }
      });}

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched == false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(function(e){
      $('.popup').hide();
      $(".popoverlay").remove();
      $('body').css('overflow', '');
    });
    $('.popup').click(function(e){
      e.stopPropagation();
    });
  </script>


  

  

  

  


</body>
</html>
